home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / lib / tex / wsltex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-08-10  |  22.5 KB  |  943 lines

  1. /* program Wsltex */
  2.  
  3.     /*
  4.     ********************************************************************
  5.     Copy an 8-bit file  to a 7-bit file,  turning characters with bit  8
  6.     set into 4-character octal escape sequences \nnn.  This is useful in
  7.     analyzing  WordStar  microcomputer   word  processor  files.    Many
  8.     sequences which  can be  recognized as  doing something  useful  are
  9.     turned into LaTeX command sequences.   Comments  below  describe the
  10.     sequences which are recognized and translated.
  11.  
  12.     Usage:
  13.  
  14.     @WSLTEX WordStar_inputfile >LaTeX_outputfile
  15.  
  16.     Remarks:
  17.     This program was converted automatically  from Pascal to C by  James
  18.     Peterson's Pascal-to-C translator  from Carnegie-Mellon  University.
  19.     Hand editing  was required  on  all I/O  references, which  are  not
  20.     converted satisfactorily (e.g.  the  Pascal file variable points  to
  21.     the current input character returned by get(), while in C, one  must
  22.     explicitly save the result of getc()).  Comment and type declaration
  23.     formatting where also  rearranged by hand.   Defined constants  were
  24.     changed to upper-case following the usual convenient C convention of
  25.     visible differences between variables  and constants, and  functions
  26.     and macros.
  27.  
  28.     The conversion of a test  188K Ph.D. thesis file produced  identical
  29.     results with both versions.  Pascal compilation was much faster than
  30.     the PCC compiler.  The conversion  time with the Pascal version  was
  31.     15.5 sec.  In the C version using putc(), it was 25.1 sec;  changing
  32.     putc() to use of write() with large buffers further reduced the time
  33.     to 21.2 sec.
  34.  
  35.     [21-Dec-85]        conversion from Pascal
  36.     [11-Oct-85]        original version
  37.     ********************************************************************
  38.     */
  39.  
  40.  
  41. #define    UNIX
  42.  
  43. #include <stdio.h>
  44. #ifdef    TOPS20
  45. #include <file.h>        /* for TOPS-20 open magic */
  46. #endif
  47.  
  48. #ifdef UNIX
  49. #define WRITELN(fp) putc('\n',fp)
  50. #else
  51. #define WRITELN(fp) {putc('\r',fp);putc('\n',fp);}
  52. #endif
  53.  
  54. #ifdef TOPS20
  55. #define EMPTY_BUFFER {if (the_next > 0) \
  56.     _write(fileno(LaTeX_file),the_buffer,the_next);\
  57.     the_next = 0;}
  58. #else
  59. #define EMPTY_BUFFER {if (the_next > 0) \
  60.     write(fileno(LaTeX_file),the_buffer,the_next);\
  61.     the_next = 0;}
  62. #endif
  63.  
  64. typedef int BOOLEAN;
  65.  
  66. #define FALSE 0
  67.  
  68. #define TRUE 1
  69.  
  70. #define NUL '\0'
  71.  
  72. #define BEL '\07'
  73.  
  74. #define CR '\r'
  75.  
  76. #define ESC '\033'
  77.  
  78. #define FF '\f'
  79.  
  80. #define HT '\t'
  81.  
  82. #define LF '\n'
  83.  
  84. #define MAXRING 256        /* limit for character ring */
  85.  
  86. #define MAXSPECIAL 100        /* limit for warning when special
  87.                 strings (underline, bold, etc) exceed
  88.                 this length */
  89.  
  90. #define MAXBUF 16384        /* large buffer for I/O efficiency */
  91.  
  92. #define UNSET 0x8000        /* use most-negative 16-bit integer */
  93.  
  94. FILE *WordStar_file;        /* 8-bit input file */
  95. FILE *LaTeX_file;        /* 7-bit or 8-bit output file */
  96.  
  97. char *the_buffer;        /* the output buffer (malloc()'ed) */
  98. int  the_next;            /* index of next empty slot in
  99.                 the_buffer[]*/
  100.  
  101. int ring_index;            /* index into ring[] */
  102. char ring[MAXRING+1];        /* ring buffer for current output
  103.                 context */
  104.  
  105. BOOLEAN hyphen_break;        /* hyphen break flag */
  106. BOOLEAN eol;            /* end-of-line flag */
  107. BOOLEAN is_underline;        /* underline et al flags */
  108. BOOLEAN is_subscript;
  109. BOOLEAN is_superscript;
  110. BOOLEAN is_bold;
  111. BOOLEAN is_alternate;
  112.  
  113. int bi_eol;            /* input byte offset at end-of-line */
  114. int bi_underline;
  115. int bi_subscript;
  116. int bi_superscript;
  117. int bi_bold;
  118. int bi_alternate;
  119.  
  120. int bo_eol;            /* output byte offset at end-of-line */
  121. int bo_underline;
  122. int bo_subscript;
  123. int bo_superscript;
  124. int bo_bold;
  125. int bo_alternate;
  126.  
  127. int input_byte_offset;
  128. int output_byte_offset;
  129. int last_c;            /* previous input character */
  130.  
  131. /* global functions */
  132.  
  133. #ifdef TOPS20
  134. #define Begin_alternate Beg_alternate    /* unique to 6 characters */
  135. #define Begin_boldface  Beg_boldface
  136. #endif
  137.  
  138. void Begin_alternate ();
  139. void Begin_boldface ();
  140. void End_alternate ();
  141. void End_boldface ();
  142. void Line_feed ();
  143. void Superscript ();
  144. void Subscript ();
  145. void Underline ();
  146. void Warning ();
  147. void W_byte ();
  148. void W_char ();
  149. void W_octal ();
  150. void W_string ();
  151.  
  152. char *strchr();
  153.  
  154.  
  155. /**********************************************************************/
  156. /*-->main */
  157. main(argc,argv)            /* Main -- WSLTEX */
  158. int argc;
  159. char *argv[];
  160. {
  161.     int fp;
  162.     register int c;        /* current input character */
  163.     register int c7;        /* low-order 7 bits of c */
  164.  
  165.     if (argc < 2)
  166.     {
  167.         fprintf(stderr,
  168.         "%%Usage: %s WordStar_infile >LaTeX_outfile",argv[0]);
  169.         WRITELN(stderr);
  170.         exit(1);
  171.     }
  172.  
  173.     /* only 7-bit bytes required, so stdout is okay to use provided
  174.     it does not do CRLF <--> LF translation.  On TOPS-20, this is
  175.     suppressed by loading this program with a special version of the I/O
  176.     library. */
  177.  
  178.     LaTeX_file = stdout;
  179.  
  180. #ifdef TOPS20
  181.     /* Read file in bytesize 8 with binary flag set to prevent
  182.        CRLF <--> LF mapping; the "rb" or "wb" flag is not sufficient for
  183.        this because PCC-20 maintains two places internally
  184.        where the binary flag is set, and both are used!  */
  185.  
  186.     if ((fp =
  187.         open(argv[1], FATT_RDONLY | FATT_SETSIZE | FATT_BINARY,8)) >= 0)
  188.         WordStar_file = fdopen(fp,"rb");
  189.     else
  190.         WordStar_file = (FILE *)NULL;
  191. #else
  192.     WordStar_file = fopen(argv[1],"rb");
  193. #endif
  194.  
  195.     if (WordStar_file == (FILE *)NULL)
  196.     {
  197.  
  198.         fprintf(stderr,
  199.         "?Open failure on WordStar input file [%s]",argv[1]);
  200.         WRITELN(stderr);
  201.         exit(1);
  202.     }
  203.  
  204.     /* Initializations -- in alphabetical order */
  205.  
  206.     bi_alternate = -1;
  207.     bi_bold = -1;
  208.     bi_subscript = -1;
  209.     bi_superscript = -1;
  210.     bi_underline = -1;
  211.     bo_alternate = -1;
  212.     bo_bold = -1;
  213.     bo_subscript = -1;
  214.     bo_superscript = -1;
  215.     bo_underline = -1;
  216.     eol = TRUE;
  217.     hyphen_break = FALSE;
  218.     input_byte_offset = -1;
  219.     is_bold = FALSE;
  220.     is_subscript = FALSE;
  221.     is_superscript = FALSE;
  222.     is_underline = FALSE;
  223.     last_c = -1;
  224.     output_byte_offset = -1;
  225.  
  226.     for (ring_index=0; ring_index <= MAXRING; ring_index++)
  227.         ring[ring_index] = ' ';
  228.     ring_index = 0;
  229.  
  230.     if ((the_buffer = (char *)malloc(MAXBUF)) == (char *)NULL)
  231.     {
  232.         fprintf(stderr,
  233.         "?Unable to allocate output buffer of size %d",MAXBUF);
  234.     WRITELN(stderr);
  235.     exit(1);
  236.     }
  237.     the_next = 0;
  238.  
  239.    /*
  240.    =====================================================================
  241.    WordStar makes heavy use of the 8-th (high-order) bit of 8-bit ASCII
  242.    characters.  In general, it turns on that bit for
  243.    -- any character (0..127) at end-of-word
  244.    -- any character (0..127) at end-of-line
  245.    -- "hard" line break on CTL-M
  246.    -- "hard" page break on CTL-L
  247.  
  248.    A discretionary hyphen (which can be removed on joining the lines) at
  249.    end-of-line is encoded as "-\215" (i.e. "-<\200|CTL-M>").
  250.  
  251.    A required hyphen  falling at end-of-line  is encoded as  "-\040\215"
  252.    (i.e.  followed by a space).
  253.  
  254.    Comment lines and WordStar command lines begin with a dot.
  255.  
  256.    "Hard"    line    breaks    are    encoded    as    \215\015    (i.e.
  257.    "<\200|CTL-M><CTL-J>"); these occur between double-space lines.
  258.  
  259.    "Soft" line breaks are encoded as <CTL-M><CTL-J>; these occur at
  260.    paragraph ends.
  261.  
  262.    Centered text is stored centered without any special markings.
  263.  
  264.    Underlined text is bracketed by CTL-S.
  265.  
  266.    Boldface text is bracketed by CTL-E ..text.. CTL-R.
  267.  
  268.    Superscripts are bracketed by CTL-T.
  269.  
  270.    Subscripts are bracketed by CTL-V.
  271.  
  272.    Alternate typewheel strings appear as CTL-Q ..text.. CTL-W.  Some of
  273.    these at least are mnemonic (e = epsilon, m = mu, . = centered dot).
  274.  
  275.    CTL-R also appears after all sub/superscript sequences, apparently
  276.    functioning as a "return to normal" state.
  277.    =====================================================================
  278.    */
  279.  
  280.     while ((c = getc(WordStar_file)) != EOF)
  281.     {
  282.         if (c < 32) /* ordinary control character */
  283.         {
  284.             switch (c)
  285.             {
  286.             case 0:
  287.             case 1:
  288.             case 2:
  289.             case 3:
  290.             case 4:    /* CTL-@ .. CTL-D */
  291.                 W_octal(c);
  292.                 break;
  293.  
  294.             case 5:    /* CTL-E */
  295.                 Begin_boldface();
  296.                 break;
  297.  
  298.             case 6:
  299.             case 7:
  300.             case 8:    /* CTL-F .. CTL-H */
  301.                 W_octal(c);
  302.                 break;
  303.  
  304.             case 9:    /* CTL-I */
  305.                 W_byte(HT);
  306.                 break;
  307.  
  308.             case 10:    /* CTL-J */
  309.                 Line_feed();
  310.                 break;
  311.  
  312.             case 11:    /* CTL-K */
  313.                 W_octal(c);
  314.                 break;
  315.  
  316.             case 12:    /* CTL-L */
  317.                 W_byte(FF);
  318.                 break;
  319.  
  320.             case 13:    /* CTL-M */
  321.                 if (last_c == (int)('-'))
  322.                     hyphen_break = TRUE;
  323.                 else if (!hyphen_break)
  324.                     W_byte(CR);
  325.                 break;
  326.  
  327.             case 14:
  328.             case 15:
  329.             case 16:    /* CTL-N .. CTL-P */
  330.                 W_octal(c);
  331.                 break;
  332.  
  333.             case 17:    /* CTL-Q */
  334.                 Begin_alternate();
  335.                 break;
  336.  
  337.             case 18:    /* CTL-R */
  338.                 if (is_bold)
  339.                     End_boldface();
  340.                 /* ELSE discard character */
  341.                 break;
  342.  
  343.             case 19:    /* CTL-S */
  344.                 Underline();
  345.                 break;
  346.  
  347.             case 20:    /* CTL-T */
  348.                 Superscript();
  349.                 break;
  350.  
  351.             case 21:    /* CTL-U */
  352.                 W_octal(c);
  353.                 break;
  354.  
  355.             case 22:    /* CTL-V */
  356.                 Subscript();
  357.                 break;
  358.  
  359.             case 23:    /* CTL-W */
  360.                 End_alternate();
  361.                 break;
  362.  
  363.             case 24:
  364.             case 25:
  365.             case 26:
  366.             case 27:
  367.             case 28:
  368.             case 29:
  369.             case 30:
  370.             case 31:    /* CTL-X .. CTL-_ */
  371.                 W_octal(c);
  372.                 break;
  373.             }
  374.             /* case */
  375.         }
  376.         else if (strchr("#$%&~_^\\{}",c))
  377.             /* LaTeX special characters must be quoted by backslash */
  378.         {
  379.             W_char('\\');
  380.             W_byte(c);
  381.         }
  382.         else if (c == (int)('.'))    /* check for WordStar comment */
  383.         {
  384.             if (eol)
  385.                 W_string("%-WS-% ");
  386.             W_byte(c);
  387.         }
  388.         else if (c < 128) /* c in 32 .. 127 */
  389.             W_byte(c);
  390.         else  /* c > 127 */
  391.         {
  392.             c7 = c & 0177;    /* lop off 8-th bit */
  393.             switch (c7)
  394.             {
  395.             case 0:    /* CTL-@ */
  396.                 W_octal(c7);
  397.                 break;
  398.  
  399.             case 1:    /* CTL-A */
  400.                 W_octal(c7);
  401.                 break;
  402.  
  403.             case 2:    /* CTL-B */
  404.                 W_octal(c7);
  405.                 break;
  406.  
  407.             case 3:    /* CTL-C */
  408.                 W_octal(c7);
  409.                 break;
  410.  
  411.             case 4:    /* CTL-D */
  412.                 W_octal(c7);
  413.                 break;
  414.  
  415.             case 5:    /* CTL-E */
  416.                 Begin_boldface();
  417.                 break;
  418.  
  419.             case 6:    /* CTL-F */
  420.                 W_octal(c7);
  421.                 break;
  422.  
  423.             case 7:    /* CTL-G */
  424.                 W_octal(c7);
  425.                 break;
  426.  
  427.             case 8:    /* CTL-H */
  428.                 W_octal(c7);
  429.                 break;
  430.  
  431.             case 9:    /* CTL-I */
  432.                 W_byte(HT);
  433.                 break;
  434.  
  435.             case 10:    /* CTL-J */
  436.                 Line_feed();
  437.                 break;
  438.  
  439.             case 11:    /* CTL-K */
  440.                 W_octal(c7);
  441.                 break;
  442.  
  443.             case 12:    /* CTL-L */
  444.                 W_byte(FF);
  445.                 break;
  446.  
  447.             case 13:    /* CTL-M */
  448.                 if (last_c == (int)('-'))
  449.                     hyphen_break = TRUE;
  450.                 else if (!hyphen_break)
  451.                 {
  452.                     if (bo_eol < output_byte_offset)
  453.                         W_byte(CR);
  454.                     /* not double space */
  455.                 }
  456.                 break;
  457.  
  458.             case 14:    /* CTL-N */
  459.                 W_octal(c7);
  460.                 break;
  461.  
  462.             case 15:    /* CTL-O */
  463.                 W_octal(c7);
  464.                 break;
  465.  
  466.             case 16:    /* CTL-P */
  467.                 W_octal(c7);
  468.                 break;
  469.  
  470.             case 17:    /* CTL-Q */
  471.                 Begin_alternate();
  472.                 break;
  473.  
  474.             case 18:    /* CTL-R */
  475.                 if (is_bold)
  476.                     End_boldface();
  477.                 /* ELSE discard character */
  478.                 break;
  479.  
  480.             case 19:    /* CTL-S */
  481.                 Underline();
  482.                 break;
  483.  
  484.             case 20:    /* CTL-T */
  485.                 Superscript();
  486.                 break;
  487.  
  488.             case 21:    /* CTL-U */
  489.                 W_octal(c7);
  490.                 break;
  491.  
  492.             case 22:    /* CTL-V */
  493.                 Subscript();
  494.                 break;
  495.  
  496.             case 23:    /* CTL-W */
  497.                 End_alternate();
  498.                 break;
  499.  
  500.             case 24:    /* CTL-X */
  501.                 W_octal(c7);
  502.                 break;
  503.  
  504.             case 25:    /* CTL-Y */
  505.                 W_octal(c7);
  506.                 break;
  507.  
  508.             case 26:    /* CTL-Z */
  509.                 W_octal(c7);
  510.                 break;
  511.  
  512.             case 27:    /* CTL-[ */
  513.                 W_octal(c7);
  514.                 break;
  515.  
  516.             case 28:    /* CTL-\ */
  517.                 W_octal(c7);
  518.                 break;
  519.  
  520.             case 29:    /* CTL-] */
  521.                 W_octal(c7);
  522.                 break;
  523.  
  524.             case 30:    /* CTL-^ */
  525.                 W_octal(c7);
  526.                 break;
  527.  
  528.             case 31:    /* CTL-_ */
  529.                 W_octal(c7);
  530.                 break;
  531.  
  532.             case 32:
  533.             case 33:
  534.             case 34:
  535.             case 35:
  536.             case 36:
  537.             case 37:
  538.             case 38:
  539.             case 39:
  540.             case 40:
  541.             case 41:
  542.             case 42:
  543.             case 43:
  544.             case 44:
  545.             case 45:
  546.                 W_byte(c7);
  547.                 break;
  548.  
  549.             case 46:    /* period */
  550.                 if (eol)
  551.                     W_string("%-WS-% ");
  552.                 W_byte(c7);
  553.                 break;
  554.  
  555.             case 47:
  556.             case 48:
  557.             case 49:
  558.             case 50:
  559.             case 51:
  560.             case 52:
  561.             case 53:
  562.             case 54:
  563.             case 55:
  564.             case 56:
  565.             case 57:
  566.             case 58:
  567.             case 59:
  568.             case 60:
  569.             case 61:
  570.             case 62:
  571.             case 63:
  572.             case 64:
  573.             case 65:
  574.             case 66:
  575.             case 67:
  576.             case 68:
  577.             case 69:
  578.             case 70:
  579.             case 71:
  580.             case 72:
  581.             case 73:
  582.             case 74:
  583.             case 75:
  584.             case 76:
  585.             case 77:
  586.             case 78:
  587.             case 79:
  588.             case 80:
  589.             case 81:
  590.             case 82:
  591.             case 83:
  592.             case 84:
  593.             case 85:
  594.             case 86:
  595.             case 87:
  596.             case 88:
  597.             case 89:
  598.             case 90:
  599.             case 91:
  600.             case 92:
  601.             case 93:
  602.             case 94:
  603.             case 95:
  604.             case 96:
  605.             case 97:
  606.             case 98:
  607.             case 99:
  608.             case 100:
  609.             case 101:
  610.             case 102:
  611.             case 103:
  612.             case 104:
  613.             case 105:
  614.             case 106:
  615.             case 107:
  616.             case 108:
  617.             case 109:
  618.             case 110:
  619.             case 111:
  620.             case 112:
  621.             case 113:
  622.             case 114:
  623.             case 115:
  624.             case 116:
  625.             case 117:
  626.             case 118:
  627.             case 119:
  628.             case 120:
  629.             case 121:
  630.             case 122:
  631.             case 123:
  632.             case 124:
  633.             case 125:
  634.             case 126:
  635.                 W_byte(c7);
  636.                 break;
  637.  
  638.             case 127:
  639.                 W_octal(c7);
  640.                 break;
  641.  
  642.             default:
  643.                 W_octal(c7);
  644.                 break;
  645.             }                /* CASE */
  646.         }
  647.         last_c = c;
  648.         input_byte_offset++;
  649.     }
  650.     EMPTY_BUFFER;
  651. }
  652. /* Main -- WSLTEX */
  653.  
  654.  
  655. /**********************************************************************/
  656. /*-->Begin_alternate */
  657. void
  658. Begin_alternate ()
  659. {
  660.     if (is_alternate)
  661.         Warning("BEGIN ALTERNATE CHARACTER SET command encounted inside\
  662.  alternate sequence",
  663.         bo_alternate,output_byte_offset);
  664.     bi_alternate = input_byte_offset;
  665.     bo_alternate = output_byte_offset;
  666.     is_alternate = TRUE;
  667.     W_string("{\\alt ");
  668. }
  669. /* Begin_alternate */
  670.  
  671.  
  672. /**********************************************************************/
  673. /*-->Begin_boldface */
  674. void
  675. Begin_boldface ()
  676. {
  677.     if (is_bold)
  678.         Warning("BEGIN BOLDFACE command encountered inside boldface",
  679.         bo_bold,output_byte_offset);
  680.     bi_bold = input_byte_offset;
  681.     bo_bold = output_byte_offset;
  682.     is_bold = TRUE;
  683.     W_string("{\\bf ");
  684. }
  685. /* Begin_boldface */
  686.  
  687. /**********************************************************************/
  688. /*-->End_alternate */
  689. void
  690. End_alternate ()
  691. {
  692.     if (is_alternate)
  693.     {
  694.         if ((bo_alternate + MAXSPECIAL) < output_byte_offset)
  695.             Warning("Long ALTERNATE CHARACTER SET sequence",
  696.             bo_alternate,output_byte_offset);
  697.     }
  698.     else
  699.         Warning("END ALTERNATE CHARACTER SET command encountered\
  700.  outside alternate text",bo_alternate,output_byte_offset);
  701.     is_alternate = FALSE;
  702.     W_byte((int)('}'));
  703. }
  704. /* End_alternate */
  705.  
  706.  
  707. /**********************************************************************/
  708. /*-->End_boldface */
  709. void
  710. End_boldface ()
  711. {
  712.     if (is_bold)
  713.     {
  714.         if ((bo_bold + MAXSPECIAL) < output_byte_offset)
  715.             Warning("Long BOLDFACE sequence",
  716.             bo_bold,output_byte_offset);
  717.     }
  718.     else
  719.         Warning("END BOLDFACE command encountered outside boldface",
  720.         bo_bold,output_byte_offset);
  721.     is_bold = FALSE;
  722.     W_byte((int)('}'));
  723. }
  724. /* End_boldface */
  725.  
  726.  
  727. /**********************************************************************/
  728. /*-->Line_feed */
  729. void
  730. Line_feed ()
  731. {
  732.     if (hyphen_break)        /* discard line break */
  733.         hyphen_break = FALSE;
  734.     else
  735.     {
  736.         if (bo_eol < output_byte_offset)    /* text on line */
  737.             W_byte(LF);
  738.         else  /* empty line */
  739.         {
  740.             if (last_c != (0200 | CR))
  741.                 W_byte(LF);
  742.         }
  743.     }
  744. }
  745. /* Line_feed */
  746.  
  747.  
  748. /**********************************************************************/
  749. /*-->strchr() */
  750. char *
  751. strchr(s,c)    /* return pointer to c in s[], or (char*)NULL */
  752. char *s;
  753. char c;
  754. {
  755.     while (*s && (*s != c))
  756.         ++s;
  757.     if (*s == c)
  758.         return (s);
  759.     else
  760.         return ((char *)NULL);
  761. }
  762. /* strchr */
  763.  
  764.  
  765. /**********************************************************************/
  766. /*-->Superscript */
  767. void
  768. Superscript ()
  769. {
  770.     if (is_superscript)
  771.     /* ending old superscript */
  772.     {
  773.         if ((bo_superscript + MAXSPECIAL) < output_byte_offset)
  774.             Warning("Long SUPERSCRIPT sequence",
  775.             bo_superscript,output_byte_offset);
  776.         W_byte((int)('}'));
  777.     }
  778.     else  /* beginning new superscript */
  779.     {
  780.         bi_superscript = input_byte_offset;
  781.         bo_superscript = output_byte_offset;
  782.         W_string("^{");
  783.     }
  784.     is_superscript = !is_superscript;
  785. }
  786. /* Superscipt */
  787.  
  788.  
  789. /**********************************************************************/
  790. /*-->Subscript */
  791. void
  792. Subscript ()
  793. {
  794.     if (is_subscript)
  795.     /* ending old superscript */
  796.     {
  797.         if ((bo_subscript + MAXSPECIAL) < output_byte_offset)
  798.             Warning("Long SUBSCRIPT sequence",
  799.             bo_subscript,output_byte_offset);
  800.         W_byte((int)('}'));
  801.     }
  802.     else  /* beginning new superscript  */
  803.     {
  804.         bi_subscript = input_byte_offset;
  805.         bo_subscript = output_byte_offset;
  806.         W_string("_{");
  807.     }
  808.     is_subscript = !is_subscript;
  809. }
  810. /* Subscript */
  811.  
  812.  
  813. /**********************************************************************/
  814. /*-->Underline */
  815. void
  816. Underline ()
  817. {
  818.     if (is_underline)
  819.     /* ending old underline */
  820.     {
  821.         if ((bo_underline + MAXSPECIAL) < output_byte_offset)
  822.             Warning("Long UNDERLINE sequence",
  823.             bo_underline,output_byte_offset);
  824.         W_byte((int)('}'));
  825.     }
  826.     else  /* beginning new underline */
  827.     {
  828.         bi_underline = input_byte_offset;
  829.         bo_underline = output_byte_offset;
  830.         W_string("{\\em ");
  831.     }
  832.     /* underlined text is \emphasized in LaTeX */
  833.     is_underline = !is_underline;
  834. }
  835. /* Underline */
  836.  
  837.  
  838. /**********************************************************************/
  839. /*-->Warning */
  840. void
  841. Warning (s,b1,b2)
  842. char s[];
  843. int b1, b2 /* output byte range, or UNSET,UNSET */;
  844. {
  845.     int k;
  846.     WRITELN(stderr);   /* !!!! temporary for debugging !!!! */
  847.     WRITELN(stderr);   /* !!!! temporary for debugging !!!! */
  848.     fprintf(stderr,
  849.     "------------------------------------------------------------");
  850.     WRITELN(stderr);
  851.     fprintf(stderr,"%s",s);
  852.     WRITELN(stderr);
  853.     if (b1 != UNSET)
  854.     {
  855.         fprintf(stderr,"\toutput byte range  = %d .. %d",b1,b2);
  856.         WRITELN(stderr);
  857.     }
  858.     fprintf(stderr,"\tinput byte offset  = %d",input_byte_offset);
  859.     WRITELN(stderr);
  860.     fprintf(stderr,"\toutput byte offset = %d",output_byte_offset);
  861.     WRITELN(stderr);
  862.     fprintf(stderr,"\tcurrent context = [");
  863.     WRITELN(stderr);
  864.     for (k=ring_index; k <= MAXRING; k++)
  865.         putc(ring[k],stderr);
  866.     for (k=0; k <= ((MAXRING + ring_index - 1) % MAXRING); k++)
  867.         putc(ring[k],stderr);
  868.     WRITELN(stderr);
  869.     fprintf(stderr,"\t]");
  870.     WRITELN(stderr);
  871.     fprintf(stderr,
  872.     "------------------------------------------------------------");
  873.     WRITELN(stderr);
  874. }
  875. /* Warning */
  876.  
  877.  
  878. /**********************************************************************/
  879. /*-->W_byte */
  880. void
  881. W_byte (c)
  882. int c;
  883. {
  884.     ring[ring_index] = (char)c;
  885.     ring_index = (ring_index++) % MAXRING;
  886.  
  887.     /* All output bytes go through this single piece of code, so
  888.     we optimize output by buffering it in large blocks.  The use
  889.     of write() instead of fwrite() avoids CR LF <--> LF translation
  890.     on most machines, and on some is significantly more efficient. */
  891.  
  892.     if (the_next >= MAXBUF)
  893.         EMPTY_BUFFER;
  894.     the_buffer[the_next++] = c;
  895.  
  896.     eol = (c == LF);
  897.     output_byte_offset++;
  898.     if (eol)
  899.     {
  900.         bi_eol = input_byte_offset;
  901.         bo_eol = output_byte_offset;
  902.     }
  903. }
  904. /* W_byte */
  905.  
  906.  
  907. /**********************************************************************/
  908. /*-->W_char */
  909. void
  910. W_char (c)
  911. char c;
  912. {
  913.     W_byte((int)(c));
  914. }
  915. /* W_char */
  916.  
  917.  
  918. /**********************************************************************/
  919. /*-->W_octal */
  920. void
  921. W_octal (c)
  922. int c;
  923. {
  924.     c = c & 0377;
  925.     W_byte((int)('\\'));
  926.     W_byte((c >> 6) + (int)('0'));
  927.     W_byte(((c >> 3) & 07) + (int)('0'));
  928.     W_byte((c & 07) + (int)('0'));
  929. }
  930. /* W_octal */
  931.  
  932.  
  933. /**********************************************************************/
  934. /*-->W_string */
  935. void
  936. W_string (s)
  937. char *s;
  938. {
  939.     while (*s)
  940.         W_byte((int)(*s++));
  941. }
  942. /* W_string */
  943.